package com.bom.boot.easy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.bom.boot.easy.cache.ElMapCacheService;
import com.bom.boot.easy.cache.XmlCacheService;
import com.bom.boot.easy.core.Result;
import com.bom.boot.easy.entity.OptionEntity;
import com.bom.boot.easy.entity.OptionInEntity;
import com.bom.boot.easy.entity.OptionOutEntity;
import com.bom.boot.easy.entity.OptionOutEntity.OptionOutId;
import com.bom.boot.easy.facade.dto.BaseDTO;
import com.bom.boot.easy.repository.OptionOutRepository;
import com.bom.boot.easy.repository.OptionRepository;
import com.bom.boot.easy.service.BomService;
import com.github.pagehelper.Page;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Log4j2
@Transactional
public class BomServiceImpl implements BomService {
    private final OptionRepository optionRepository;
    private final OptionOutRepository optionOutRepository;
    private final ElMapCacheService elMapCacheService;
    private final XmlCacheService xmlCacheService;

    @Override
    public Result<Object> execute(BaseDTO dto) {
        OptionEntity option = optionRepository.findOneById_NameAndId_Page_Name(dto.get("_option", String.class), dto.get("_page", String.class));
        Set<OptionInEntity> optionIns = option.getOptionIns();
        for (OptionInEntity optionIn : optionIns) {
            dto.validFormat(optionIn, elMapCacheService);//验证参数并格式化数据
        }
        Result<Object> rs = new Result<>();
        //执行相关操作
        switch (option.getType()) {
            case SEARCH:
                List<Map<String, Object>> list;
                if (dto.containsKey("num") && dto.containsKey("size")) {
                    Page<Map<String, Object>> page = xmlCacheService.page(option.getDs(), option.getKey(), dto, MapUtil.getInt(dto, "num"), MapUtil.getInt(dto, "size"));
                    list = page.getResult();
                    rs.setTotal(page.getTotal());
                } else {
                    list = xmlCacheService.list(option.getDs(), option.getKey(), dto);
                }
                rs.setData(list);//page.getResult()
                rs.setCode(200);
                rs.setSuccess(true);
                rs.setMsg("success");

                Set<OptionOutEntity> optionOuts = option.getOptionOuts();
                if (CollectionUtil.isEmpty(optionOuts) && CollectionUtil.isNotEmpty(list)) {
                    log.info("手动添加返回结果");
                    Map<String, Object> e = list.get(0);
                    List<OptionOutEntity> optionOutEntities = new LinkedList<>();
                    for (Map.Entry<String, Object> col : e.entrySet()) {
                        OptionOutEntity optionOutEntity = new OptionOutEntity();
                        optionOutEntity.setId(new OptionOutId(option, col.getKey()));
                        optionOutEntity.setTitle(col.getKey());
                        optionOutEntities.add(optionOutEntity);
                    }
                    optionOutRepository.saveAllAndFlush(optionOutEntities);
                } else {
                    if (CollectionUtil.isNotEmpty(optionOuts)) {
                        Map<String, OptionOutEntity> keyValue = optionOuts.stream().collect(Collectors.toMap(e -> e.getId().getName(), e -> e));
                        list.forEach(e -> {//data
                            for (Map.Entry<String, Object> col : e.entrySet()) {
                                OptionOutEntity optionOutEntity = keyValue.get(col.getKey());
                                if (StrUtil.isNotBlank(optionOutEntity.getFormat())) {
                                    if (col.getValue() != null) {
                                        e.put(col.getKey(), dto.formatEl(optionOutEntity.getFormat(), elMapCacheService, e));
                                    }
                                }
                                if (StrUtil.isNotBlank(optionOutEntity.getAlias())) {
                                    e.put(optionOutEntity.getAlias(), col.getValue());
                                    e.remove(col.getKey());
                                }
                            }
                        });
                    }
                }
                break;
            default:
                break;
        }

        return rs;
    }

    @Override
    public Result<List<Map<String, Object>>> search(BaseDTO dto) {
        String ds = MapUtil.getStr(dto, "_ds");
        String key = MapUtil.getStr(dto, "_key");
        Result<List<Map<String, Object>>> rs = new Result<>();
        if (dto.containsKey("num") && dto.containsKey("size")) {
            log.info("分页查询");
            Page<Map<String, Object>> page = xmlCacheService.page(ds, key, dto, MapUtil.getInt(dto, "num"), MapUtil.getInt(dto, "size"));
            rs.setData(page.getResult());
            rs.setTotal(page.getTotal());
        } else {
            List<Map<String, Object>> list = xmlCacheService.list(ds, key, dto);
            rs.setData(list);
        }
        rs.setCode(200);
        rs.setSuccess(true);
        rs.setMsg("success");
        return rs;
    }

    @Override
    public Result<Map<String, Object>> detail(BaseDTO dto) {
        String ds = MapUtil.getStr(dto, "_ds");
        String key = MapUtil.getStr(dto, "_key");
        Result<Map<String, Object>> rs = new Result<>();
        rs.setData(xmlCacheService.detail(ds, key, dto));
        rs.setCode(200);
        rs.setSuccess(true);
        rs.setMsg("success");
        return rs;
    }
}
